package com.tiny.climber;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import com.tiny.core.game.Game;
import com.tiny.core.game.GameObject;
import com.tiny.core.game.states.GameState;
import com.tiny.core.game.states.StateBasedGame;
import com.tiny.core.graphics.camera.Camera2d;
import com.tiny.core.input.KeyboardManager;
import com.tiny.core.physics.CollisionDetector;
import com.tiny.core.physics.PhysicGameObject;
import com.tiny.core.physics.SimpleGravityManager;
import com.tiny.core.physics.Vector;
import com.tiny.core.resources.ImageManager;
import com.tiny.effects.FadeInOutEffect;
import com.tiny.utils.GameObjectManager;
import com.tiny.utils.Timer;

public class ClimbGame implements GameState {

    private List<GameObject> objects;
    private CollisionDetector collisor;
    private GameObjectManager objectManager;
    private SimpleGravityManager gravityManager;
    private Camera2d camera;

    private TinyClimber climber;

    private Random r = new Random();

    private static final int PLATAFORM_WIDTH = 200;
    private static final int PLATAFORM_HEIGHT = 25;
    private static final int PLATAFORM_INTERVAL = 200;;

    private int game_width;

    private int last_plataform_created;

    private Timer timer;
    private int lastSecLava;
    private int lastSecPtero;
    private EvilLava lava;
    private int distance;

    private Font font;

    private ImageManager images;
    private Ptero ptero;

    private boolean gameOver;
    private FadeInOutEffect fadeOut;

    @Override
    public void onLoad(StateBasedGame game) {
        fadeOut = new FadeInOutEffect(game, false, 1000);
        gameOver = false;
        images = new ImageManager();
        images.loadImage("img/climber.png");
        images.loadImage("img/tiny-jump.png");

        images.loadImage("img/hector.png");
        images.loadImage("img/clock.png");

        font = new Font("Verdana", Font.BOLD, 13);

        timer = new Timer(game);
        timer.start();
        lastSecLava = 0;
        lastSecPtero = 0;

        game_width = game.getWidth();

        // Inicia os objetos
        objects = new ArrayList<GameObject>();
        collisor = new CollisionDetector(objects);
        objectManager = new GameObjectManager(objects);

        List<GameObject> plataforms = createPlataforms(5, game_width);
        objects.addAll(plataforms);

        climber = new TinyClimber((int) plataforms.get(0).getPos().x, (int) plataforms.get(0).getPos().y - 200,
                game.getMovimentCalculator(), images);
        lava = new EvilLava((int) (plataforms.get(0).getPos().y + 100), game);
        objects.add(lava);

        List<PhysicGameObject> objs = new ArrayList<PhysicGameObject>();
        objs.add(climber);
        objects.add(climber);
        gravityManager = new SimpleGravityManager(objs, 20d);

        last_plataform_created = (int) plataforms.get(plataforms.size() - 1).getPos().y;

        camera = new Camera2d(game, climber);
        camera.setBoundsX(new Vector(0, 800));
        camera.setObjectsToManage(objects);
    }

    private List<GameObject> createPlataforms(int quantidade, int start) {

        List<GameObject> plataforms = new ArrayList<GameObject>();
        int x;
        for (int i = 0; i < quantidade; i++) {
            x = r.nextInt(800);
            while (x + PLATAFORM_WIDTH > game_width) {
                x = r.nextInt(800);
            }
            plataforms.add(new Plataform(x, start - (i * PLATAFORM_INTERVAL), PLATAFORM_WIDTH, PLATAFORM_HEIGHT));
        }
        return plataforms;
    }

    @Override
    public void onRender(Graphics2D g, StateBasedGame game) {
        if (gameOver) {
            fadeOut.render(g);
        }
        Graphics2D g2 = (Graphics2D) g.create();
        camera.render(g2);

        g.setColor(Color.WHITE);
        g.fillRect(game_width - 210, 20, 80, 20);
        g.setColor(Color.DARK_GRAY);
        g.drawRect(game_width - 210, 20, 80, 20);
        g.setColor(Color.BLACK);
        g.setFont(font);
        g.drawString("Time: " + timer.getSeconds(), game_width - 200, 35);

        g.setColor(Color.WHITE);
        g.fillRect(game_width - 210, 45, 200, 20);
        g.setColor(Color.DARK_GRAY);
        g.drawRect(game_width - 210, 45, 200, 20);
        g.setColor(Color.BLACK);
        g.setFont(font);
        g.drawString("Lava Distance: " + distance, game_width - 200, 60);
    }

    @Override
    public void onUnload(StateBasedGame game) {

    }

    @Override
    public void onUpdate(int currentTick, StateBasedGame game) {

        if (KeyboardManager.getInstance().isPressed(KeyEvent.VK_ESCAPE)) {
            game.enterState(Main.MENU);
        }

        if (gameOver) {
            fadeOut.update(currentTick);
            if (fadeOut.isFinished()) {
                game.enterState(Main.MENU);
            }
            return;
        }
        timer.countTick();
        gravityManager.update();
        collisor.update();
        objectManager.update(currentTick);

        camera.update(currentTick);

        // Criando as plataformas conforme o jogador vai avancando
        if (Math.abs(last_plataform_created - climber.getPos().y) < PLATAFORM_INTERVAL / 2) {
            List<GameObject> os = createPlataforms(3, last_plataform_created - PLATAFORM_INTERVAL);
            for (GameObject gameObject : os) {
                objectManager.add(gameObject);
            }
            last_plataform_created = (int) os.get(os.size() - 1).getPos().y;
        }

        if (climber.getPos().x < 0) {
            climber.getPos().x = game_width - climber.getPos().width;
        }

        if (climber.getPos().x > game_width) {
            climber.getPos().x = 0;
        }

        if (climber.getPos().y + climber.getPos().height >= lava.getPos().y) {
            gameOver = true;
            fadeOut.start();
        }

        if (lastSecLava != timer.getSeconds() && timer.getSeconds() % 2 == 0) {
            lava.setLavaVel(lava.getLavaVel() + 5);
        }
        lastSecLava = timer.getSeconds();

        if (ptero == null && lastSecPtero != timer.getSeconds() && timer.getSeconds() % 10 == 0) {
            createPtero(game);
        }
        lastSecPtero = timer.getSeconds();

        distance = (int) Math.abs(lava.getPos().y - climber.getPos().y);
    }

    private void createPtero(Game game) {
        ptero = new Ptero(r.nextInt(1) * game_width, (int) (climber.getPos().y - 500), r.nextBoolean(), this, images,
                game.getMovimentCalculator());
        objectManager.add(ptero);
    }

    public int getGameWidth() {
        return game_width;
    }

    public void removePtero() {
        ptero = null;
    }

    public void slowLava() {
        lava.setLavaVel(lava.getLavaVel() - 2);
    }
}
